/***************************************************************************************************
  *Copyright(C),2010-2016,Sumscope
  *FileName	:  BaseString.h
  *Author	:  scofined.qi
  *Version	:  1.0
  *Date		:  2016/01/12
  *Desc		:  //用于主要说明此程序文件完成的主要功能
  *Relation :  
  *Others	:  //其他内容说明
  *Function :  //主要函数列表，每条记录应包含函数名及功能简要说明
  *History	:  //修改历史记录列表，每条修改记录应包含修改日期、修改者及修改内容简介
***************************************************************************************************/
#pragma once

#include "TinyString.h"
#include "../core.h"

namespace qb{
namespace base{
	template<typename T>
	class StackArrayImpl{
	protected:
		T*			m_ptr;			// 指向堆上的数据,有可能与m_buf相等
		int			m_capcity;		// 堆内存m_ptr的实际空间大小
		int			m_size;			// 对内存m_ptr或者栈内存m_buf中装载的数据大小
		T*			m_buf;			// 指向栈上的数据
	public:
		StackArrayImpl() :m_size(0), m_capcity(0), m_ptr(NULL), m_buf(NULL)
		{

		}
		StackArrayImpl(T* buf,int capcity):m_size(0),m_capcity(capcity),m_ptr(buf),m_buf(buf)
		{
			
		}
		~StackArrayImpl()
		{
			if(m_ptr && m_ptr!=m_buf)
				delete [] m_ptr;
		}
		void Add(const T& T1){
			Add(&T1, 1);
		}
		void Add(const T* buf,int size)
		{
			if (buf == 0)return;
			if (sizeof(T) == sizeof(char))
			{
				size = size <= 0 ? strlen((const char*)buf) : size;
			}
			if (size <= 0)return;
			if(m_ptr==m_buf && m_size+size<m_capcity)
			{
				memcpy(m_buf+m_size,buf,size*sizeof(T));
				m_size+=size;
			}else
			{
				int extra = size + 1;
				int half = m_size / 2;
				int plus = extra < half ? half : extra;
				T* mem = new T[m_size + plus];
				memcpy(mem, m_ptr, m_size*sizeof(T));
				memcpy(mem + m_size, buf, size*sizeof(T));
				memset(mem + m_size + size, 0, (plus - size)*sizeof(T));
				if (m_ptr && m_ptr != m_buf)
					delete[] m_ptr;
				m_ptr = mem;
				m_capcity = m_size + plus-1;
				m_size = m_size + size;
			}
		}

		operator const T*()const{return m_ptr;}
		operator T*(){ return m_ptr; }
		int size()const{return m_size;}
		T* GetBuf(){return m_ptr;}
		const T& at(int pos)const{return m_ptr[pos];}
		T& at(int pos){ return m_ptr[pos]; }
	protected:
		void SetSizeImpl(int size,int N)
		{
			if (m_ptr != m_buf)//堆
			{
				if (size > N)
				{
					if (size > m_capcity)
					{
						if (m_ptr)delete[] m_ptr;
						m_ptr = new T[size];
						m_capcity = size;
					}
					m_size = size;
					memset(m_ptr, 0, sizeof(T)*m_capcity);
				}
				else
				{
					if (m_ptr)delete[] m_ptr;
					m_ptr = m_buf;
					m_capcity = N;
					m_size = size;
				}
			}
			else
			{
				m_capcity = N;
				m_size = size;
			}
		}
		void Clear(){
			// 清除,以便可以再装载,复用内存
			m_size = 0;
			if (m_ptr && m_ptr!=m_buf && m_capcity > 0)
				memset(m_ptr, 0, m_capcity);
		}
	};
	template<typename T,int N>
	class StackArray : public StackArrayImpl<T>{				// 当加入的内容小于N，那么在栈上分配,超过配额在堆上分配
		T		m_real_buf[N];		// 
	public:
		StackArray(){
			memset(m_real_buf,0,sizeof(T)*N);
			StackArrayImpl<T>::m_capcity = N;
			StackArrayImpl<T>::m_buf = m_real_buf;
			StackArrayImpl<T>::m_ptr = m_real_buf;
		}
		int StackCapcity()const{return N;}
		void Reset()
		{
			memset(m_real_buf, 0, sizeof(T)*N);
			StackArrayImpl<T>::Clear();
		}
		void SetSize(int size){
			memset(m_real_buf, 0, sizeof(T)*N);
			StackArrayImpl<T>::SetSizeImpl(size, N);
		}
	};
    class S_CORE_EXPORT BaseString{
	public:
		typedef BaseString ThisType;
		typedef char Element;
		enum{INIT_CAPCITY=16,npos=-1};
	protected:
		int			m_size;
		int			m_capcity;
		Element*	m_string;
		Element		m_null[2];
	public://constructors
		BaseString();
		BaseString(int capcity);
		BaseString(const Element* str);
		BaseString(const Element* str,int len);
		BaseString(const ThisType& bs);
		~BaseString();

		BaseString(BaseString&& bs);
		BaseString& operator=(BaseString&& bs);

		ThisType& operator=(const Element* str);
		ThisType& operator=(const ThisType& bs);
		ThisType& operator=(Element c);
		void expand(int size);
		static inline int  length(const Element* str){return str?strlen(str):0;}
	public://operations
		void clear();
		void reset();

		ThisType& assign(Element c);
		ThisType& assign(const Element* str);
		ThisType& assign(const Element* str,int len);
		ThisType& assign(const ThisType& br);

		ThisType& append(Element c);
		ThisType& append(int count,Element c );
		ThisType& append(const Element* str);
		ThisType& append(const Element* str,int len);
		ThisType& append(const ThisType& br);


		ThisType& push_back(Element c);
		ThisType& push_back(const Element* str);
		ThisType& push_back(const Element* str,int len);
		ThisType& push_back(const ThisType& br);

		ThisType& insert(int pos,const Element* str,int len);
		ThisType& erase(int pos,int len=1);

		ThisType& replace(int pos,int len,const Element* str,int size);
		int find(Element c,int offset=0)const;
		int find(const Element* str,int offset=0)const;
		int rfind(Element c,int offset=0)const;
		void substr(int offset,int len,ThisType& bs)const;
		ThisType substr(int offset,int len)const;
		int compare(const Element* str,int len)const;
		void swap(ThisType& bs);
	public://operators
		//ThisType& operator+(const ThisType& bs){return append(bs);}
		//ThisType& operator+(const Element c){return append(c);}
		ThisType  operator+(const ThisType& bs)const{ThisType ret(*this);ret.append(bs);return ret;}

		bool operator==(const ThisType& bs)const{return compare(bs.m_string,bs.m_size)==0;}
		bool operator==(const Element* str)const{return compare(str,length(str))==0;}
		bool operator!=(const ThisType& bs)const{return compare(bs.m_string,bs.m_size)!=0;}
		bool operator!=(const Element* str)const{return compare(str,length(str))!=0;}
	public://accessors
		const Element* c_str()const{return (m_string!=0 && m_size>0)?m_string:m_null;}
		Element* c_str(){ return (m_string != 0 && m_size>0) ? m_string : m_null; }
		operator const Element*()const{ return c_str(); }
		int size()const{return m_size;}
		int capcity()const{return m_capcity;}
		bool empty()const{return !m_string || m_size<=0;}
		Element at(int i)const;
		Element& at(int i);
		Element operator[](int i)const{return at(i);}
		Element& operator[](int i){return at(i);}
		static int SearchString(const Element *mainStr,int mainStrLen,const Element *subStr,int subStrLen,bool ic);
	};

	S_CORE_EXPORT BaseString& operator+=(BaseString& bs,const BaseString::Element* str);
	S_CORE_EXPORT BaseString& operator+=(BaseString& bs,const BaseString& plus);
	S_CORE_EXPORT bool operator<(const BaseString& left,const BaseString& right);

	/*
		KeyString 主要用于std::map的first参数,用于降低内存开销
		尤其是对于平均长度<=3  或者平均长度>=15
		
		取n为字符串长度,总共需要的内存由如下关系:
					n<=3   n<=15    n<=255   n<=65536
		std::string 24     24       n+25     n+25
		KeyString   4      n+6      n+6      n+7
		当长度<=15的情况下,越接近15,相对于std::string,KeyString节省的内存越少
			长度越小节省越多
		长度>=16,总是比std::string节省19个字节,节省与长度无关

		如何针对只有1-2个字符的字符串进行优化编码???
		考虑到在32平台下,指针的最高位始终为0,有效虚拟地址空间为0-2g(2^31)
		因此,把31位当做模式,当为1,表示指针模式,为0,表示编码模式

		KeyString 可以处于两种模式
			指针模式	m_data的最高位为1,低31位构成一个指针,指向超过3个字符的字符串
						并且m_data指向的内容中,开头1-2个字节,表示长度
						第一个字节的最高位如果为1,长度用2个字节表示
						第一个字节的最高位如果为0,长度用1个字节表示
						指针模式下,内存占用为4+1/2+字符串长度+1个字节零结尾
			编码模式	m_data的最高位为0,m_raw为一个数组,m_raw[3]为0,同时31位也为0
						编码模式下,内存占用为4个字节

		劣势:
			当一般的函数参数为std::string时,如果容器主键类型为KeyString,可能导致每次查找都要
			将std::string转化为KeyString,需要多做一次转化步骤,即内存分配
			如何避免这种多余的性能损耗?
			1.移除长度数据编码,使得获取长度的时间复杂度为O(N)
			2.然后构造一个临时的KeyString子类,伪造一个指针,析构的时候,将指针清空
	*/
	class S_CORE_EXPORT KeyString{
		typedef KeyString ThisType;
	public:
		enum : uint64_t {
			HighBit = 0x80,				// 首个字符的最高位
			MostBitFlag = (sizeof(uintptr_t) == 4 ?0x80000000 : 0x8000000000000000LL),	// 最高位
			LowBitMask = 0x7F,			// 首个字符的第七位掩码
			TinyLength = 1 << 7,		// 短字符串长度,超过此值需要用2个字符存储长度
			MaxLength = (1 << 15) - 1	// 最大字符串长度,长于此值截断
		};
	protected:
		union{
			const char*	m_data;			// 
			char		m_raw[4];		// 
		};
	public:
		~KeyString();
		KeyString();
		KeyString(const char* str);
		KeyString(const char* str, int len);
		KeyString(const std::string& str);
		KeyString(const ThisType& str);
		KeyString(ThisType&& str);
		KeyString& operator=(ThisType&& str);
		KeyString& operator=(const char* str);
		KeyString& operator=(const KeyString& str);
		KeyString& operator+=(const ThisType& str);
		KeyString& operator+=(const char* str);
		const char* c_str()const;

		void Reset(){
			destroy();
		}
		int size()const;
		int bytes()const;
		bool empty()const{ return size() <= 0; }
		operator const char*()const{ return c_str(); }
		bool operator<(const ThisType& str)const
		{
			return scompare(c_str(), size(), str.c_str(), str.size()) < 0;
		}
		bool operator<(const char* str)const
		{
			return scompare(c_str(), size(), str, str ? strlen(str) : 0) < 0;
		}
		bool operator>(const char* str)const
		{
			return scompare(c_str(), size(), str, str ? strlen(str) : 0) > 0;
		}
		bool operator>(const ThisType& str)const
		{
			return scompare(c_str(), size(), str.c_str(), str.size())>0;
		}
		bool operator==(const ThisType& str)const;
		bool operator==(const char* str)const;
		bool assign_plus(const char* str, int len, const char* post, int postLen);
		bool assign(const char* str, int len);
	protected:
		static inline int scompare(const char* self, int slen, const char* str, int len)
		{
			if (slen <= 0 && len <= 0)return 0;
			else if (slen <= 0)return -1;
			else if (len <= 0)return 1;
			return strcmp(self, str);
		}
		inline bool istiny() const
		{
			return m_data != nullptr && !(MostBitFlag & (static_cast<uintptr_t>(reinterpret_cast<uintptr_t>(m_data))));
		}
		void destroy();
		bool haspointer()const;
		inline const char* pointer()const{
			return (const char*)((static_cast<uintptr_t>(reinterpret_cast<uintptr_t>(m_data))) & ~MostBitFlag);
		}
		inline void set_pointer(const char* ptr){
			m_data = (const char*)((static_cast<uintptr_t>(reinterpret_cast<uintptr_t>(ptr))) | MostBitFlag);
		}
		inline void set_length(char* data, int total)const
		{
			if (total >= TinyLength){
				data[0] = (total >> 8) | 0x80;
				data[1] = total & 0x00ff;	//低8位
			}
			else
				data[0] = total;
		}
	};
}
}

